linux启动过程
加载BIOS
当按电源,计算机首先会加载BIOS程序,其中包含了CPU的相关信息、设备启动顺序信息、硬盘信息、内存信息、时钟信息等。读取MBR
硬盘上第0磁道第一个扇区被称为MBR(Master Boot Record)即主引导记录,大小为512直接。MBR中有一段程序(bootload,占446字节)。系统找到BIOS所指定的硬盘的MBR后,就会将其复制到0×7c00地址所在的物理内存中。其实被复制到物理内存的内容就是Boot Loader,而具体就是lilo、grub或者grup2。Boot Loader
MBR中有一段程序bootload,占446字节。这段程序会根据MBR中的分区表查找活动分区。找到操作系统的所在的分区,并加载操作系统的内核。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核做好一切准备。当bootload获得控制权,就没BIOS什么事了。以grup2为例又可分为三个阶段:- stage 1:由于引导记录必须非常的小(446字节),因此stage 1 的唯一功能就是定位并加载阶段 1.5 的代码。为了完成此任务,stage 1.5 的代码必须位于引导记录与设备第一个分区之间的位置。
- stage 1.5:引导记录与设备第一个分区之间的位置由于历史上的技术原因(CHS:answer)而空闲。第一个分区的开始位置在扇区 63 和 MBR(扇区 0)之间遗留下 62 个 512 字节的扇区(共 31744 字节),用于存储stage 1.5 的代码镜像 core.img 文件。stage1.5有识别文件系统的能力,此后grub才有能力去访问/boot分区/boot/grub目录下的 stage2文件,将stage2载入内存并执行。
- stage 2:GRUB stage 2 所有的文件都已存放于 /boot/grub2 目录及其几个子目录之下。该阶段主要功能是定位和加载 Linux 内核到内存中,并转移控制权到内核。
加载kernel
内核取得整个系统的控制权,bootload退出,内存完成解压缩后会探测每个硬件。访问根所在的分区。文件系统,进程管理,内存管理,网络管理,安全功能,驱动程序。至此,Linux内核已经建立起来了,基于Linux的程序应该可以正常运行了。init进程(init/upstart/systemd)
- SysVinit
SysVinit 顺序运行(串行),概念简单清晰、启动慢。启动流程如下:
init—->inittab(runlevel)—->rc.sysinit(系统初始化)—->rc—->rcX.d(启停服务)—->rc.local—->tty和login
缺点:频繁地使用硬件热插拔技术,SysVinit需要默认就启动所有可能使用的硬件对应的服务;启动慢。 Upstart
Upstart 采用事件驱动模型。更快地启动系统(并行);当新硬件被发现时动态启动服务;硬件被拔除时动态停止服务。UpStart 主要的概念是 job 和 event。Job 就是一个工作单元,用来完成一件工作,比如启动一个后台服务,或者运行一个配置命令。每个 Job 都等待一个或多个事件,一旦事件发生,upstart 就触发该 job 完成相应的工作。
开机upstart首先产生startup事件。systemd
systemd 的最大特点有两个:
(1)提供了比 UpStart 更激进的并行启动能力,采用了 socket / D-Bus activation 等技术启动服务。更快的启动速度。
(2)用 CGroup 统计跟踪子进程,干净可靠。并行化Socket
对于传统的 Unix daemon,彼此的真正依赖是服务所提供的 socket。
如果能尽早建立客户程序所必须的 socket 而令客户程序处于等待状态而不是在服务程序完全启动后再启动客户程序,我们就能加快启动进程,进一步并行化进程启动。并行化Bus服务
Linux上现代的daemon都通过DBus而非socket来交互。
DBus已经提供了所有必要的hook:使用DBus将会在第一次访问时加载服务,并且给予最小的、每请求一个的、消费 者与生产者同时启动的同步机制。
总结如下:基于Socket和基于DBus的服务可一次并行启动所有进程,无需任何额外的同步。基于激活的策略还能令我们进行延迟加载服务。 如果服务很少被用到,我们可以在第一次被访问时启动,而不是在启动过程中启动。并行化文件系统任务
系统启动过程中,文件系统相关的活动是最耗时的,比如挂载文件系统,fsck,磁盘配额检查等。
Systemd 集成了 autofs 的实现,对于系统中的挂载点,比如/home,当系统启动的时候,systemd 为其创建一个临时的自动挂载点。在这个时刻/home 真正的挂载设备尚未启动好,真正的挂载操作还没有执行,文件系统检测也还没有完成。可是那些依赖该目录的进程已经可以并发启动,他们的 open()操作被内建在 systemd 中的 autofs 捕获,将该 open()调用挂起(可中断睡眠状态)。然后等待真正的挂载操作完成,文件系统检测也完成后,systemd 将该自动挂载点替换为真正的挂载点,并让 open()调用返回。由此,实现了那些依赖于文件系统的服务和文件系统本身同时并发启动。
- SysVinit
小结
GRUB2、systemd 初始化系统是大多数现代 Linux 发行版引导和启动的关键组件。尽管在实际中,systemd 的使用还存在一些争议,但是 GRUB2 与 systemd 可以密切地配合先加载内核,然后启动一个业务系统所需要的系统服务。
Fast Booting Approach
精简内核模块
这种方法主要通过去除系统启动过程中的非必需的外设硬件的驱动、初始化过程及内核的启动序列来降低启动时间。
这种方法一般主要应用于嵌入式系统领域,针对目标系统做出高度定制化的优化方案,能够大大降低系统的启动时间,但是这种方法会降低系统的兼容性以及对其他硬件、外设的支持,很难应用在通用计算机的优化上。Non-Volatile Memory
非易失性存储器使得boot过程中的一些步骤不再必需(例如:把kernel image搬入内存)。目前,主要应用在手机、smart TV、嵌入式设备领域。BOOTING LINUX FASTER:提出通过非易失性内存实现使用每次启动系统仅使用同一个内核镜像。免去了每次启动加载镜像、解压缩等操作。
Booting Time Minimization for Real-Time Embedded Systems with Non-Volatile Memory :结合DRAM和非易失性存储器形式化模拟了实时嵌入式系统的启动时间最小化问题,解决了启动时间最小化问题与数学技术之间的对应关系。 通过在最坏情况执行时间(WCET)分析的支持将目标问题抽象为整数线性规划(ILP)。
文章中还应用了XIP(eXecute-In-Place) 技术来加速启动,XIP能够直接跳过加载程序步骤,通过非易失性存储器存储完整的文件系统和内核、应用。
同时在操作系统启动过程中,内核的解压过程也带来了大量的时间开销,把内核作为文件系统的一部分存储在flash中,是内核不再需要压缩,也可以加速操作系统启动。
Hibernation/Snapshot
Improving Linux Startup Time Using Software Resume:提出一种snapshot的软件恢复方式,它本质上是一种从磁盘恢复操作,它是从存储在 disk 或者 flash memory上的半永久性快照映像恢复系统,恢复计算机到已知的运行状态。而与标准的恢复不同是的snapshot只需要制作一次,后续可以不断的重复使用同一个snapshot恢复系统。此外还有一些论文中提到多种技术的融合,以及虚拟机的快速启动方案:
BB: Booting Booster for Consumer Electronics with Modern OS:提出了Booting Booster机制,可以快速初始化系统,更早的启动关键的应用和服务。
VirtMan: design and implementation of a fast booting system for homogeneous virtual machines in iVCE∗: VirtMan构建了一个有效的VMI存储路径(可能是raw,qcow2等),无需等待完整的映像数据准备完毕即可启动VM OS。 VirtMan系统主要包含两个模块,即Volt Coordinator和VirtMan Compute。VirtMan Compute节点以层级方式(由Volt协调)附加现有安装点的映像,在本地缓存映像数据,并在基于缓存的快照之上启动VM。
总结
目前操作系统启动的流程基本满足上述的5大步骤,加载BIOS,读取MBR两个步骤属于固定模式,考虑到兼容性较难优化;BootLoader主流的有两类grup、grup2、RedBoot主要用于pc、服务器的启动,而uboot主要应用于嵌入式环境。
加载内核和init进程是当下比较热门的优化方向,并且在整个操作系统的启动过程中占比较大,针对嵌入式环境有精简内核、启动项、flash等手段来加速启动流程,并且针对特定应用场景的内核、启动项精简往往可以代开较大的收益。针对通用计算机而言目前主要还是在于硬件升级(NVM,SSD),优化启动进程(并行、依赖关系等,目前systemd已做出了较激进的优化,有大统一的趋势)。
针对嵌入式场景可以通过深度定制较便捷地实现快速启动,而针对通用计算机,由于其应用场景复杂多变的情况可能需要针对kernel加载,init进程方面有进行大幅优化或重新设计,以及升级硬件等方式实现快速启动。就目前而言服务器和个人pc启动速度已经较快,对于更快速启动的需求不是很强烈。